package net.siufung.boot.caffeine.autoconfigure;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.boot.caffeine.properties.CaffeineProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 缓存配置
 * @author 陈建峰
 * @since 2022/2/9 11:10 下午
 */
@Slf4j
@EnableCaching
@Configuration
@EnableConfigurationProperties({ CaffeineProperties.class })
@AllArgsConstructor
public class CaffeineAutoConfig {

    private final CaffeineProperties properties;
	
	@Bean
	public CacheManager caffeineCacheManager() {
		SimpleCacheManager cacheManager = new SimpleCacheManager();
        Map<String, CaffeineCache> cacheMap = Maps.newHashMap();
        /* 设置全局配置的本地缓存 */
//        List<String> globalCacheNames = properties.getCacheName();
//        if (!Objects.isNull(globalCacheNames) && !CollectionUtils.isEmpty(globalCacheNames)) {
//            addCacheObject(cacheMap, globalCacheNames, properties.getSpec());
//        }
        /* 设置自定义属性缓存, 可以覆盖全局缓存 */
        List<CaffeineProperties.Config> configs = properties.getConfigs();
        if(!Objects.isNull(configs) && !CollectionUtils.isEmpty(configs)){
            for (CaffeineProperties.Config config : configs) {
                List<String> cacheNames = config.getCacheName();
                if (!Objects.isNull(cacheNames) && !CollectionUtils.isEmpty(cacheNames)) {
                		addCacheObject(cacheMap, cacheNames, config.getSpec());
                }
            }
        }
        /* 加入到缓存管理器进行管理 */
        cacheManager.setCaches(cacheMap.values());
        return cacheManager;
	}
	
	private void addCacheObject(Map<String, CaffeineCache> cacheMap, List<String> cacheNames, String spec) {
		for (String cacheName : cacheNames) {
			/* 初始化 */
			Caffeine<Object, Object> recordStats = Caffeine.from(spec).recordStats();
			/* 监听 */
			recordStats.removalListener((key, value, cause) -> log.debug("缓存键 [{}], 缓存值 [{}] 被淘汰的原因为: [{}]", key, value, cause));
	        /* 构建 */
			Cache<Object, Object> cache = recordStats.build();
			CaffeineCache caffeineCache = new CaffeineCache(cacheName, cache);
	        /* 覆盖/添加 */
	        cacheMap.put(cacheName, caffeineCache);
		}
	}
	
}
